package com.cloud.custom.common.utils;

import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.sql.DataSource;

import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;

import redis.clients.jedis.Jedis;

/**
 * 工具类，基于Redis生成数据库主键序列
 * 
 * @author taominglong
 *
 */
public class RedisKeyHelper {
	private static final String REDIS_TEMPLATE_BEAN_NAME = "redisTemplate";
	private static final int RETRY_LOCK_TIMES = 3;
	private static final String LOCK_SUCCESS = "OK";
	private static final String SET_IF_NOT_EXIST = "NX";
	private static final String SET_WITH_EXPIRE_TIME = "PX";
	private static final Long RELEASE_SUCCESS = 1L;
	private static final String LOCK_SUFFIX = "_LOCK";
	private static final String RELEASE_LOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";


	/**
	 * 尝试获取分布式锁
	 * 
	 * @param jedis
	 *            我们使用key来当锁，因为key是唯一的
	 * @param lockKey
	 * @param requestId
	 * @param expireTime
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static boolean tryDistributeLock(String lockKey, String requestId, int expireTime) {
		@SuppressWarnings("rawtypes")
		RedisTemplate redisTemplate = (RedisTemplate) SpringBeanHelper.getBean(REDIS_TEMPLATE_BEAN_NAME);
		return (boolean) redisTemplate.execute((RedisCallback<Boolean>) redisConnection -> {
			Jedis jedis = (Jedis) redisConnection.getNativeConnection();
			String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
			if (LOCK_SUCCESS.equals(result)) {
				return Boolean.TRUE;
			}
			return Boolean.FALSE;
		});
	}

	/**
	 * 分布式锁解锁
	 * 
	 * @param jedis
	 * @param lockKey
	 *            分布式锁KEY值
	 * @param requestId
	 *            解锁客户端
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static boolean releaseDistributeLock(String lockKey, String requestId) {
		@SuppressWarnings("rawtypes")
		RedisTemplate redisTemplate = (RedisTemplate) SpringBeanHelper.getBean(REDIS_TEMPLATE_BEAN_NAME);
		return (boolean) redisTemplate.execute((RedisCallback<Boolean>) redisConnection -> {
			Jedis jedis = (Jedis) redisConnection.getNativeConnection();
			Object result = jedis.eval(RELEASE_LOCK_SCRIPT, Collections.singletonList(lockKey),
					Collections.singletonList(requestId));
			if (RELEASE_SUCCESS.equals(result)) {
				return Boolean.TRUE;
			}
			return Boolean.FALSE;
		});
	}

	/**
	 * 是否存在key
	 * 
	 * @param key
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private static boolean exists(final String key) {
		@SuppressWarnings("rawtypes")
		RedisTemplate redisTemplate = (RedisTemplate) SpringBeanHelper.getBean(REDIS_TEMPLATE_BEAN_NAME);

		return (boolean) redisTemplate.execute((RedisCallback<Boolean>) redisConnection -> {
			Jedis jedis = (Jedis) redisConnection.getNativeConnection();
			if (jedis.exists(key)) {
				return true;
			}
			return false;
		});
	}

	/**
	 * 获取并自增
	 * 
	 * @param key
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private static Long getAndIncrement(final String key) {
		@SuppressWarnings("rawtypes")
		RedisTemplate redisTemplate = (RedisTemplate) SpringBeanHelper.getBean(REDIS_TEMPLATE_BEAN_NAME);

		return (long) redisTemplate.execute((RedisCallback<Long>) redisConnection -> {
			Jedis jedis = (Jedis) redisConnection.getNativeConnection();
			return jedis.incr(key);
		});

	}
}
